﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace TimeTracker
{
    static class Program
    {
        /// <summary>
        /// Extern for Idle Detection
        /// </summary>
        /// <param name="plii">LASTINPUTINFO Reference</param>
        /// <returns>true / false if Extern was successful, changes LASTINPUTINFO.dwTime 
        /// to reflect the time when the last update was made</returns>
        [DllImport("User32.dll")]
        private static extern bool
                GetLastInputInfo(ref LASTINPUTINFO plii);

        /// <summary>
        /// Structure to contain Last Input Time
        /// </summary>
        internal struct LASTINPUTINFO
        {
            public uint cbSize;

            public uint dwTime;
        }

        /// <summary>
        /// Returns the time the last system input was received.
        /// </summary>
        /// http://www.codeproject.com/KB/cs/GetIdleTimeWithCS.aspx
        public static uint LastInputTime
        {
            get
            {
                // Initilize the structure
                LASTINPUTINFO lastInPut = new LASTINPUTINFO();

                // 
                lastInPut.cbSize = (uint)
                    System.Runtime.InteropServices.Marshal.SizeOf(lastInPut);

                GetLastInputInfo(ref lastInPut);

                return lastInPut.dwTime;
            }
        }


        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(true);

            Properties.Settings.Default.SettingsSaving += new System.Configuration.SettingsSavingEventHandler(TimeTracker.Miscellaneous.SettingsEvents.Default_SettingsSaving);

            Form1 frmTracker = new Form1();
            Application.Run(frmTracker);
        }

        /// <summary>
        /// Release any unneeded resources
        /// </summary>
        /// http://stackoverflow.com/questions/263234/-net-minimize-to-tray-and-minimize-required-resources
        public static void MinimizeMemory()
        {
            
            GC.Collect(GC.MaxGeneration);
            GC.WaitForPendingFinalizers();
            SetProcessWorkingSetSize(
                Process.GetCurrentProcess().Handle,
                (UIntPtr)0xFFFFFFFF,
                (UIntPtr)0xFFFFFFFF);

            IntPtr heap = GetProcessHeap();

            if (HeapLock(heap))
            {
                try
                {
                    if (HeapCompact(heap, 0) == 0)
                    {
                        // error condition ignored
                    }
                }
                finally
                {
                    HeapUnlock(heap);
                }
            }
        }

        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool SetProcessWorkingSetSize(
            IntPtr process,
            UIntPtr minimumWorkingSetSize,
            UIntPtr maximumWorkingSetSize);

        [DllImport("kernel32.dll", SetLastError = true)]
        internal static extern IntPtr GetProcessHeap();

        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool HeapLock(IntPtr heap);

        [DllImport("kernel32.dll")]
        internal static extern uint HeapCompact(IntPtr heap, uint flags);

        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool HeapUnlock(IntPtr heap);
    }
}
